package org.baojie.raft.connector.server.handler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.baojie.raft.box.Box;
import org.baojie.raft.message.RaftMsgSignal;
import org.baojie.raft.message.RaftMessage;
import org.baojie.raft.message.VoteResponse;
import org.baojie.raft.message.info.Message;
import org.baojie.raft.message.info.MessageInfo;
import org.baojie.raft.serialization.RaftSerialize;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RaftServerHandler extends SimpleChannelInboundHandler<byte[]> {

    private static final Logger log = LoggerFactory.getLogger(RaftServerHandler.class);

    private final RaftSerialize serialize = RaftSerialize.getInstance();
    private final Box box;

    public RaftServerHandler(Box box) {
        this.box = box;
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, byte[] msg) throws Exception {
        RaftMessage message = serialize.deserialize(msg, RaftMessage.class);
        MessageInfo entity = message.getMessage();
        Message.Type type = entity.type();
        if (Message.Type.Ping == type) {
            box.putPing(message);
        } else if (Message.Type.Pong == type) {
            box.dealHeartBeatPong(message);
        } else if (Message.Type.AskVote == type) {
            box.receiveVoteRequest(message);
        } else if (Message.Type.AnsVote == type) {
            VoteResponse resp = (VoteResponse) entity;
            String msgId = message.getMsgId();
            dealVoteResponse(resp, msgId);
        } else {
            log.error("message type = " + type + ", message = " + message);
        }
    }

    private void dealVoteResponse(VoteResponse resp, String msgId) {
        RaftMsgSignal signal = box.touchStartVote(msgId);
        if (null == signal) {
            log.warn("收到 vote response 信号，但是找不到信号量了");
        } else {
            String tmp = signal.getMsgId();
            if (!msgId.equals(tmp)) {
                log.warn("收到 vote response 信号，但是 msgId 不一致");
                return;
            } else {
                if (signal.isCanceled()) {
                    log.warn("收到 vote response 信号，但是 信号量已经取消 ");
                } else {
                    signal.release(resp);
                }
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.channel().close();
        log.error("raft server handler 出现异常的 channel 关闭");
    }

}

